namespace DotNetNuke.UI.Utilities
{

    
    using System;
    using System.Collections;
    using System.Configuration;
    using System.Diagnostics;
    using System.IO;
    using System.Text.RegularExpressions;
    using System.Web;
    using System.Web.Caching;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;
    using System.Xml;

    /// -----------------------------------------------------------------------------
    /// Project	 : DotNetNuke
    /// Class	 : ClientAPI
    /// -----------------------------------------------------------------------------
    /// <summary>
    /// Library responsible for interacting with DNN Client API.
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <history>
    /// [Jon Henning]	8/3/2004	Created
    /// </history>
    /// -----------------------------------------------------------------------------
    public class ClientAPI
    {
        /// -----------------------------------------------------------------------------
        /// <summary>Private variable holding location of client side js files.  Shared by entire application.</summary>
        /// -----------------------------------------------------------------------------
        private static string m_sScriptPath;
        public const string SCRIPT_CALLBACKID = "__DNNCAPISCI";
        public const string SCRIPT_CALLBACKPAGEID = "__DNNCAPISCPAGEID";
        public const string SCRIPT_CALLBACKPARAM = "__DNNCAPISCP";
        public const string SCRIPT_CALLBACKSTATUSDESCID = "__DNNCAPISCSDI";
        public const string SCRIPT_CALLBACKSTATUSID = "__DNNCAPISCSI";

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Common way to handle confirmation prompts on client
        /// </summary>
        /// <param name="objButton">Button to trap click event</param>
        /// <param name="strText">Text to display in confirmation</param>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	2/17/2005	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public static void AddButtonConfirm(WebControl objButton, string strText)
        {
            objButton.Attributes.Add("onClick", "javascript:return confirm('" + GetSafeJSString(strText) + "');");
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Determines of browser currently requesting page adaquately supports passed un client-side functionality
        /// </summary>
        /// <param name="eFunctionality">Desired Functionality</param>
        /// <returns>True when browser supports it</returns>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	8/3/2004	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public static bool BrowserSupportsFunctionality(ClientFunctionality eFunctionality)
        {
            if (HttpContext.Current == null)
            {
                return true;
            }
            HttpRequest objRequest = HttpContext.Current.Request;
            if (ClientAPIDisabled())
            {
                return false;
            }
            XmlDocument objXML = GetClientAPICapsDOM();
            bool blnSupports = false;
            string strBrowser = objRequest.Browser.Browser;
            double dblVersion = objRequest.Browser.MajorVersion + objRequest.Browser.MinorVersion;
            string strFunc = Enum.GetName(eFunctionality.GetType(), eFunctionality);
            blnSupports = CapsMatchFound(objXML.SelectSingleNode("/capabilities/functionality[@nm='" + strFunc + "']/supports"), objRequest.UserAgent, strBrowser, dblVersion);
            if (CapsMatchFound(objXML.SelectSingleNode("/capabilities/functionality[@nm='" + strFunc + "']/excludes"), objRequest.UserAgent, strBrowser, dblVersion))
            {
                blnSupports = false;
            }
            return blnSupports;
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Looks for a browser match (name supplied by .NET Framework) and processes 
        /// matches where UserAgent contains specified text
        /// </summary>
        /// <param name="objNode"></param>
        /// <param name="strAgent"></param>
        /// <param name="strBrowser"></param>
        /// <param name="dblVersion"></param>
        /// <returns></returns>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	8/20/2004	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        private static bool CapsMatchFound(XmlNode objNode, string strAgent, string strBrowser, double dblVersion)
        {
            if ((((objNode != null) && ((strAgent==null?0:strAgent.Length) > 0)) ? 1 : 0) != 0)
            {
                IEnumerator refObjectHelperL0=null;
                if (Convert.ToDouble(Convert.ToDecimal(GetSafeXMLAttr(objNode.SelectSingleNode("browser[@nm='" + strBrowser + "']"), "minversion", "999"))) <= dblVersion)
                {
                    return true;
                }
                if (objNode.SelectSingleNode("browser[@nm='*']") != null)
                {
                    return true;
                }
                XmlNodeList objContains = objNode.SelectNodes("browser[@contains]");
                try
                {
                    refObjectHelperL0 = objContains.GetEnumerator();
                    while (refObjectHelperL0.MoveNext())
                    {
                        XmlNode objContain = (XmlNode) refObjectHelperL0.Current;
                        if (strAgent.ToLower().IndexOf(GetSafeXMLAttr(objContain, "contains", "\0").ToLower()) > -1)
                        {
                            return true;
                        }
                    }
                }
                finally
                {
                    if (refObjectHelperL0 is IDisposable)
                    {
                        (refObjectHelperL0 as IDisposable).Dispose();
                    }
                }
            }
            return false;
        }

        public static bool ClientAPIDisabled()
        {
            return (ConfigurationManager.AppSettings["ClientAPI"] == "0");
        }

        public static string GetCallbackEventReference(Control objControl, string strArgument, string strClientCallBack, string strContext, string srtClientErrorCallBack)
        {
            return GetCallbackEventReference(objControl, strArgument, strClientCallBack, strContext, srtClientErrorCallBack, null);
        }

        public static string GetCallbackEventReference(Control objControl, string strArgument, string strClientCallBack, string strContext, string srtClientErrorCallBack, string strClientStatusCallBack)
        {
            if (strArgument == null)
            {
                strArgument = "null";
            }
            if (strContext == null)
            {
                strContext = "null";
            }
            if (srtClientErrorCallBack == null)
            {
                srtClientErrorCallBack = "null";
            }
            if (strClientStatusCallBack == null)
            {
                strClientStatusCallBack = "null";
            }
            string strControlID = objControl.ID;
            if ((((objControl is Page) && ((strControlID==null?0:strControlID.Length) == 0)) ? 1 : 0) != 0)
            {
                strControlID = "__DNNCAPISCPAGEID";
            }
            if (!(objControl is Page))
            {
                strControlID = strControlID + " " + objControl.ClientID;
            }
            return string.Format("dnn.xmlhttp.doCallBack('{0}',{1},{2},{3},{4},{5});", new object[] { strControlID, strArgument, strClientCallBack, strContext, srtClientErrorCallBack, strClientStatusCallBack });
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Retrieves XML Document representing the featuresets that each browser handles
        /// </summary>
        /// <returns></returns>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	8/20/2004	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        private static XmlDocument GetClientAPICapsDOM()
        {
            string strFileName = "";
            XmlDocument objXML = new XmlDocument();
            if (DataCache.GetCache("ClientAPICaps") == null)
            {
                try
                {
                    strFileName = HttpContext.Current.Server.MapPath(ScriptPath + "/ClientAPICaps.config");
                }
                catch (Exception exception1)
                {
                    
                    Exception ex = exception1;
                    
                }
                if ((((strFileName != null) && File.Exists(strFileName)) ? 1 : 0) != 0)
                {
                    objXML.Load(strFileName);
                    DataCache.SetCache("ClientAPICaps", objXML, new CacheDependency(strFileName));
                }
                return objXML;
            }
            return (XmlDocument) DataCache.GetCache("ClientAPICaps");
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Retrieves DNN Client Variable value
        /// </summary>
        /// <param name="objPage">Current page rendering content</param>
        /// <param name="strVar">Variable name to retrieve value for</param>
        /// <returns>Value of variable</returns>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	8/3/2004	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public static string GetClientVariable(Page objPage, string strVar)
        {
            string strPair = GetClientVariableNameValuePair(objPage, strVar);
            if (strPair.IndexOf(COLUMN_DELIMITER) > -1)
            {
                //return Strings.Split(strPair, COLUMN_DELIMITER, -1, CompareMethod.Binary)[1];
                return strPair.Split(COLUMN_DELIMITER.ToCharArray())[1];
            }
            return "";
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Retrieves DNN Client Variable value
        /// </summary>
        /// <param name="objPage">Current page rendering content</param>
        /// <param name="strVar">Variable name to retrieve value for</param>
        /// <param name="strDefaultValue">Default value if variable not found</param>
        /// <returns>Value of variable</returns>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	8/3/2004	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public static string GetClientVariable(Page objPage, string strVar, string strDefaultValue)
        {
            string strPair = GetClientVariableNameValuePair(objPage, strVar);
            if (strPair.IndexOf(COLUMN_DELIMITER) > -1)
            {
                //return Strings.Split(strPair, COLUMN_DELIMITER, -1, CompareMethod.Binary)[1];
                return strPair.Split(COLUMN_DELIMITER.ToCharArray())[1];
            }
            return strDefaultValue;
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Parses DNN Variable control contents and returns out the delimited name/value pair
        /// </summary>
        /// <param name="objPage">Current page rendering content</param>
        /// <param name="strVar">Name to retrieve</param>
        /// <returns>Delimited name/value pair string</returns>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	8/3/2004	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        private static string GetClientVariableNameValuePair(Page objPage, string strVar)
        {            
            HtmlInputHidden ctlVar = get_ClientVariableControl(objPage);            
            string strValue = ctlVar.Value;
            if ((strValue==null?0:strValue.Length) == 0)
            {
                strValue = HttpContext.Current.Request[ctlVar.ClientID];
            }
            if ((strValue==null?0:strValue.Length) > 0)
            {
                strValue = strValue.Replace(QUOTE_REPLACEMENT, "\"");
                int intIndex = strValue.IndexOf(ROW_DELIMITER + strVar + COLUMN_DELIMITER);
                if (intIndex > -1)
                {
                    intIndex += COLUMN_DELIMITER.Length;
                    int intEndIndex = strValue.IndexOf(ROW_DELIMITER, intIndex);
                    if (intEndIndex > -1)
                    {
                        return strValue.Substring(intIndex, intEndIndex - intIndex);
                    }
                    return strValue.Substring(intIndex);
                }
            }
            return "";
        }

        private static HtmlInputHidden get_ClientVariableControl(Page objPage)
        {
            HtmlInputHidden ctlVar = DotNetNuke.UI.Utilities.Globals.FindControlRecursive(objPage,
                "__dnnVariable") as HtmlInputHidden;
            if (ctlVar == null)
            {
                Control ctlParent;
                ctlParent = objPage.Controls[0];
                ctlVar=new HtmlInputHidden();
                ctlVar.ID = "__dnnVariable";
                ctlParent.Controls.Add(ctlVar);

            }
            return ctlVar;
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Returns javascript to call dnncore.js key handler logic
        /// </summary>
        /// <param name="intKeyAscii">ASCII value to trap</param>
        /// <param name="strJavascript">Javascript to execute</param>
        /// <returns>Javascript to handle key press</returns>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	2/17/2005	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        private static string GetKeyDownHandler(int intKeyAscii, string strJavascript)
        {
            return ("return __dnn_KeyDown('" + Convert.ToString(intKeyAscii) + "', '" + strJavascript.Replace("'", "%27") + "', event);");
        }

        public static string GetPostBackClientEvent(Page objPage, Control objControl, string arg)
        {
            return objPage.ClientScript.GetPostBackEventReference(objControl, arg);
        }

        public static string GetPostBackClientHyperlink(Control objControl, string strArgument)
        {
            return ("javascript:" + GetPostBackEventReference(objControl, strArgument));
        }

        public static string GetPostBackEventReference(Control objControl, string strArgument)
        {
            return objControl.Page.ClientScript.GetPostBackEventReference(objControl, strArgument);
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Escapes string to be safely used in client side javascript.  
        /// </summary>
        /// <param name="strString">String to escape</param>
        /// <returns>Escaped string</returns>
        /// <remarks>
        /// Currently this only escapes out quotes and apostrophes
        /// </remarks>
        /// <history>
        /// [Jon Henning]	2/17/2005	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public static string GetSafeJSString(string strString)
        {
            if (strString!=null&&strString.Length>0)
            {
                return Regex.Replace(strString, "(['\"\\\\])", @"\$1");
            }
            return strString;
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// A Safe way of accessing XML Attributes - clean way to handle nodes and attributes
        /// that are set to nothing.  When not found a "nice" default value is returned.
        /// </summary>
        /// <param name="objNode"></param>
        /// <param name="strAttr"></param>
        /// <param name="strDef"></param>
        /// <returns></returns>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	8/20/2004	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        private static string GetSafeXMLAttr(XmlNode objNode, string strAttr, string strDef)
        {
            if (objNode != null)
            {
                XmlNode objAttr = objNode.Attributes.GetNamedItem(strAttr);
                if (objAttr != null)
                {
                    return objAttr.Value;
                }
            }
            return strDef;
        }

        public static void HandleClientAPICallbackEvent(Page objPage)
        {
            string str = objPage.Request.QueryString["__DNNCAPISCI"];
            if (str!=null&&str.Length>0)
            {
                string[] arrIDs = objPage.Request.QueryString["__DNNCAPISCI"].Split(new char[] { ' ' });
                string strControlID = arrIDs[0];
                string strClientID = "";
                if (arrIDs.Length > 1)
                {
                    strClientID = arrIDs[1];
                }
                string strParam = objPage.Server.UrlDecode(objPage.Request.QueryString["__DNNCAPISCP"]);
                ClientAPICallBackResponse objResponse = new ClientAPICallBackResponse(objPage, ClientAPICallBackResponse.CallBackTypeCode.Simple);
                try
                {
                    Control objControl;
                    objPage.Response.Clear();
                    if (strControlID == "__DNNCAPISCPAGEID")
                    {
                        objControl = objPage;
                    }
                    else
                    {
                        objControl = DotNetNuke.UI.Utilities.Globals.FindControlRecursive(objPage, strControlID, strClientID);
                    }
                    if (objControl != null)
                    {
                        IClientAPICallbackEventHandler objInterface;
                        if (objControl is HtmlForm)
                        {
                            objInterface = (IClientAPICallbackEventHandler) objPage;
                        }
                        else
                        {
                            objInterface = (IClientAPICallbackEventHandler) objControl;
                        }
                        if (objInterface != null)
                        {
                            try
                            {
                                objResponse.Response = objInterface.RaiseClientAPICallbackEvent(strParam);
                                objResponse.StatusCode = ClientAPICallBackResponse.CallBackResponseStatusCode.OK;
                            }
                            catch (Exception exception1)
                            {
                                
                                Exception ex = exception1;
                                objResponse.StatusCode = ClientAPICallBackResponse.CallBackResponseStatusCode.GenericFailure;
                                objResponse.StatusDesc = ex.Message;
                                
                            }
                        }
                        else
                        {
                            objResponse.StatusCode = ClientAPICallBackResponse.CallBackResponseStatusCode.InterfaceNotSupported;
                            objResponse.StatusDesc = "Interface Not Supported";
                        }
                    }
                    else
                    {
                        objResponse.StatusCode = ClientAPICallBackResponse.CallBackResponseStatusCode.ControlNotFound;
                        objResponse.StatusDesc = "Control Not Found";
                    }
                }
                catch (Exception exception2)
                {
                    //
                    //Exception ex = exception2;
                    objResponse.StatusCode = ClientAPICallBackResponse.CallBackResponseStatusCode.GenericFailure;
                    objResponse.StatusDesc = exception2.Message;
                    
                }
                finally
                {
                    objResponse.Write();
                    objPage.Response.End();
                }
            }
        }

        public static bool IsClientScriptBlockRegistered(Page objPage, string key)
        {
            return objPage.ClientScript.IsClientScriptBlockRegistered(key);
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Responsible for registering client side js libraries and its dependecies.
        /// </summary>
        /// <param name="objPage">Current page rendering content</param>
        /// <param name="eRef">Enumerator of library to reference</param>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	8/3/2004	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public static void RegisterClientReference(Page objPage, ClientNamespaceReferences eRef)
        {
            switch (((int) eRef))
            {
                case 0:
                    if (!IsClientScriptBlockRegistered(objPage, "dnn.js"))
                    {
                        RegisterClientScriptBlock(objPage, "dnn.js", "<script src=\"" + ScriptPath + "dnn.js\"></script>");
                        if (!BrowserSupportsFunctionality(ClientFunctionality.SingleCharDelimiters))
                        {
                            RegisterClientVariable(objPage, "__scdoff", "1", true);
                        }
                    }
                    break;

                case 1:
                    RegisterClientReference(objPage, ClientNamespaceReferences.dnn);
                    break;

                case 2:
                    RegisterClientReference(objPage, ClientNamespaceReferences.dnn);
                    if (!IsClientScriptBlockRegistered(objPage, "dnn.positioning.js"))
                    {
                        RegisterClientScriptBlock(objPage, "dnn.positioning.js", "<script src=\"" + ScriptPath + "dnn.dom.positioning.js\"></script>");
                    }
                    break;

                case 3:
                    RegisterClientReference(objPage, ClientNamespaceReferences.dnn);
                    if (!IsClientScriptBlockRegistered(objPage, "dnn.xml.js"))
                    {
                        string strScript = "<script src=\"" + ScriptPath + "dnn.xml.js\"></script>";
                        if (BrowserSupportsFunctionality(ClientFunctionality.XMLJS))
                        {
                            strScript = strScript + "<script src=\"" + ScriptPath + "dnn.xml.jsparser.js\"></script>";
                        }
                        RegisterClientScriptBlock(objPage, "dnn.xml.js", strScript);
                    }
                    break;

                case 4:
                    RegisterClientReference(objPage, ClientNamespaceReferences.dnn);
                    if (!IsClientScriptBlockRegistered(objPage, "dnn.xmlhttp.js"))
                    {
                        string strScript = "<script src=\"" + ScriptPath + "dnn.xmlhttp.js\"></script>";
                        if (BrowserSupportsFunctionality(ClientFunctionality.XMLHTTPJS))
                        {
                            strScript = strScript + "<script src=\"" + ScriptPath + "dnn.xmlhttp.jsxmlhttprequest.js\"></script>";
                        }
                        RegisterClientScriptBlock(objPage, "dnn.xmlhttp.js", strScript);
                    }
                    break;
            }
        }

        public static void RegisterClientScriptBlock(Page objPage, string key, string strScript)
        {
            objPage.ClientScript.RegisterClientScriptBlock(objPage.GetType(), key, strScript);
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Registers a client side variable (name/value) pair
        /// </summary>
        /// <param name="objPage">Current page rendering content</param>
        /// <param name="strVar">Variable name</param>
        /// <param name="strValue">Value</param>
        /// <param name="blnOverwrite">Determins if a replace or append is applied when variable already exists</param>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	8/3/2004	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public static void RegisterClientVariable(Page objPage, string strVar, string strValue, bool blnOverwrite)
        {
            HtmlInputHidden ctlVar = get_ClientVariableControl(objPage);
            string strPair = GetClientVariableNameValuePair(objPage, strVar);
            if (strPair.Length > 0)
            {
                strPair = strPair.Replace("\"", QUOTE_REPLACEMENT);
                if (blnOverwrite)
                {
                    ctlVar.Value = ctlVar.Value.Replace(ROW_DELIMITER + strPair, ROW_DELIMITER + strVar + COLUMN_DELIMITER + strValue);
                }
                else
                {
                    string strOrig = GetClientVariable(objPage, strVar);
                    ctlVar.Value = ctlVar.Value.Replace(ROW_DELIMITER + strPair, ROW_DELIMITER + strVar + COLUMN_DELIMITER + strOrig + strValue);
                }
            }
            else
            {
                HtmlInputHidden refObjectHelperS0 = ctlVar;
                refObjectHelperS0.Value = refObjectHelperS0.Value + ROW_DELIMITER + strVar + COLUMN_DELIMITER + strValue;
            }
            ctlVar.Value = ctlVar.Value.Replace("\"", QUOTE_REPLACEMENT);
            System.Diagnostics.Debug.WriteLine(GetClientVariableNameValuePair(objPage, strVar));
            System.Diagnostics.Debug.WriteLine(GetClientVariable(objPage, strVar));
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Traps client side keydown event looking for passed in key press (ASCII) and hooks it up with client-side javascript
        /// </summary>
        /// <param name="objControl">Control that should trap the keydown</param>
        /// <param name="strJavascript">Javascript to execute when event fires</param>
        /// <param name="intKeyAscii">ASCII value of key to trap</param>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	2/17/2005	Commented
        /// </history>
        /// -----------------------------------------------------------------------------
        public static void RegisterKeyCapture(Control objControl, string strJavascript, int intKeyAscii)
        {
            DotNetNuke.UI.Utilities.Globals.SetAttribute(objControl, "onkeydown", GetKeyDownHandler(intKeyAscii, strJavascript));
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Traps client side keydown event looking for passed in key press (ASCII) and hooks it up with server side postback handler
        /// </summary>
        /// <param name="objControl">Control that should trap the keydown</param>
        /// <param name="objPostbackControl">Server-side control that has its onclick event handled server-side</param>
        /// <param name="intKeyAscii">ASCII value of key to trap</param>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	2/17/2005	Commented
        /// </history>
        /// -----------------------------------------------------------------------------
        public static void RegisterKeyCapture(Control objControl, Control objPostbackControl, int intKeyAscii)
        {
            DotNetNuke.UI.Utilities.Globals.SetAttribute(objControl, "onkeydown", GetKeyDownHandler(intKeyAscii, GetPostBackClientHyperlink(objPostbackControl, "")));
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Allows a listener to be associated to a client side post back
        /// </summary>
        /// <param name="objParent">The current control on the page or the page itself.  Depending on where the page is in its lifecycle it may not be possible to add a control directly to the page object, therefore we will use the current control being rendered to append the postback control.</param>
        /// <param name="strEventName">Name of the event to sync.  If a page contains more than a single client side event only the events associated with the passed in name will be raised.</param>
        /// <param name="objDelegate">Server side AddressOf the function to handle the event</param>
        /// <param name="blnMultipleHandlers">Boolean flag to determine if multiple event handlers can be associated to an event.</param>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	9/15/2004	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public static void RegisterPostBackEventHandler(Control objParent, string strEventName, ClientAPIPostBackControl.PostBackEvent objDelegate, bool blnMultipleHandlers)
        {
            Control objCtl = DotNetNuke.UI.Utilities.Globals.FindControlRecursive(objParent.Page, "ClientAPIPostBackCtl");
            if (objCtl == null)
            {
                objCtl = new ClientAPIPostBackControl(objParent.Page, strEventName, objDelegate);
                objCtl.ID = "ClientAPIPostBackCtl";
                objParent.Controls.Add(objCtl);
                RegisterClientVariable(objParent.Page, "__dnn_postBack", GetPostBackClientHyperlink(objCtl, "[DATA]"), true);
            }
            else if (blnMultipleHandlers)
            {
                ((ClientAPIPostBackControl) objCtl).AddEventHandler(strEventName, objDelegate);
            }
        }

        public static void RegisterStartUpScript(Page objPage, string key, string script)
        {
            objPage.ClientScript.RegisterStartupScript(objPage.GetType(), key, script);
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Finds __dnnVariable control on page, if not found it attempts to add its own.
        /// </summary>
        /// <param name="objPage">Current page rendering content</param>
        /// <value></value>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	8/3/2004	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        //private static HtmlInputHidden this[Page objPage]
        //{
        //    get
        //    {
        //        HtmlInputHidden ctlVar = (HtmlInputHidden) DotNetNuke.UI.Utilities.Globals.FindControlRecursive(objPage, "__dnnVariable");
        //        if (ctlVar == null)
        //        {
        //            Control ctlParent = objPage.Controls[0];
        //            ctlVar = new HtmlInputHidden();
        //            ctlVar.ID = "__dnnVariable";
        //            ctlParent.Controls.Add(ctlVar);
        //        }
        //        return ctlVar;
        //    }
        //}

        //This place maybe wrong,and I can't find the solution to slove this trouble we meet,we need static indexer
        //private static HtmlInputHidden this[Page objPage]
        //{
        //    get
        //    {
        //        HtmlInputHidden ctlVar = (HtmlInputHidden)DotNetNuke.UI.Utilities.Globals.FindControlRecursive(objPage, "__dnnVariable");
        //        if (ctlVar == null)
        //        {
        //            Control ctlParent = objPage.Controls[0];
        //            ctlVar = new HtmlInputHidden();
        //            ctlVar.ID = "__dnnVariable";
        //            ctlParent.Controls.Add(ctlVar);
        //        }
        //        return ctlVar;
        //    }
        //}


        /// -----------------------------------------------------------------------------
        /// <summary>Character used for delimiting name from value</summary>
        /// -----------------------------------------------------------------------------
        public static string COLUMN_DELIMITER
        {
            get
            {
                if (BrowserSupportsFunctionality(ClientFunctionality.SingleCharDelimiters))
                {
                    return "\x0012";
                }
                return "~|~";
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>Character used for delimiting name from value</summary>
        /// -----------------------------------------------------------------------------
        public static string CUSTOM_COLUMN_DELIMITER
        {
            get
            {
                if (BrowserSupportsFunctionality(ClientFunctionality.SingleCharDelimiters))
                {
                    return "\x0010";
                }
                return "~.~";
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>Character used for delimiting name/value pairs</summary>
        /// -----------------------------------------------------------------------------
        public static string CUSTOM_ROW_DELIMITER
        {
            get
            {
                if (BrowserSupportsFunctionality(ClientFunctionality.SingleCharDelimiters))
                {
                    return "\x000f";
                }
                return "~,~";
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>In order to reduce payload, substitute out " with different char, since when put in a hidden control it uses "</summary>
        /// -----------------------------------------------------------------------------
        public static string QUOTE_REPLACEMENT
        {
            get
            {
                if (BrowserSupportsFunctionality(ClientFunctionality.SingleCharDelimiters))
                {
                    return "\x0013";
                }
                return "~!~";
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>Character used for delimiting name/value pairs</summary>
        /// -----------------------------------------------------------------------------
        public static string ROW_DELIMITER
        {
            get
            {
                if (BrowserSupportsFunctionality(ClientFunctionality.SingleCharDelimiters))
                {
                    return "\x0011";
                }
                return "~`~";
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Path where js files are placed
        /// </summary>
        /// <value></value>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	8/19/2004	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public static string ScriptPath
        {
            get
            {
                string script = "";
                if ((m_sScriptPath==null?0:m_sScriptPath.Length) > 0)
                {
                    return m_sScriptPath;
                }
                if (HttpContext.Current == null)
                {
                    return script;
                }
                if (HttpContext.Current.Request.ApplicationPath.EndsWith("/"))
                {
                    return (HttpContext.Current.Request.ApplicationPath + "js/");
                }
                return (HttpContext.Current.Request.ApplicationPath + "/js/");
            }
            set
            {
                m_sScriptPath = value;
            }
        }

        public enum ClientFunctionality
        {
            DHTML = 1,
            Positioning = 8,
            SingleCharDelimiters = 0x80,
            XML = 2,
            XMLHTTP = 0x20,
            XMLHTTPJS = 0x40,
            XMLJS = 0x10,
            XSLT = 4
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Enumerates each namespace with a seperate js file
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// [Jon Henning]	8/3/2004	Created
        /// </history>
        /// -----------------------------------------------------------------------------
        public enum ClientNamespaceReferences
        {
            dnn,
            dnn_dom,
            dnn_dom_positioning,
            dnn_xml,
            dnn_xmlhttp
        }
    }
}

